structure TopData = 
struct
local
  fun format_dummy _ = nil
in
  (*% *)
  datatype stopAt 
    = (*% @format "SyntaxCheck" *) SyntaxCheck
    | (*% @format "ErrorCheck" *)  ErrorCheck
    | (*% @format "NameRef" *) NameRef
    | (*% @format "NoStop" *) NoStop

  (*%  @formatter(Filename.filename) Filename.format_filename *)
  datatype code 
    = (*%  @format(filename) filename *)
      FILE of Filename.filename

  (*%
     @formatter(Filename.filename) Filename.format_filename 
     @formatter(InterfaceName.source) InterfaceName.format_source
     @formatter(InterfaceName.file_load_mode)
       InterfaceName.format_file_load_mode
     @formatter(option) TermFormat.formatOptionalOption
  *)
  type options 
    = (*%
         @format({stopAt,
                  baseFilename: bas basopt, 
                  loadPath: load loads,
                  loadMode,
                  outputWarnings,
                  defaultInterface})
          "{"
           1[
              1[  "stopAt:" +d stopAt ]
               +1
              1["baseFilename:" +d basopt(bas)("SOME","NONE") ]
               +1
              1["loadPath:" +d loads(load)(".")]
               +1
              1["loadMode:" +d loadMode]
            ]
           1
           "}"
       *)
      {
        stopAt: stopAt,
        baseFilename: Filename.filename option,
        loadPath: InterfaceName.source list,
        loadMode: InterfaceName.file_load_mode,
        outputWarnings: UserError.errorInfo list -> unit,
        defaultInterface: Filename.filename -> Filename.filename
      }

  type toplevelContext =
      {
        fixEnv: Elaborator.fixEnv,
        topEnv: NameEvalEnv.topEnv,
        version: IDCalc.version,
        builtinDecls: IDCalc.icdecl list
      }

  type newContext =
      {
        fixEnv: Elaborator.fixEnv,
        topEnv: NameEvalEnv.topEnv
      }

  (*% @formatter(newContext) format_dummy *)
  datatype result 
    = (*%
         @format "stopped"
       *)
      STOPPED
    | (*% 
         @format(env * code) "return"
       *)
      RETURN of newContext * Filename.filename

(*

  (*%
     @formatter(AbsynInterface.compileUnit) AbsynInterface.format_compileUnit
   *)
  type loadFileResult 
    = (*%
         @format({loadedFiles: file files} * comileUnit)
         "{"
           1[
             1["loadedFiles:" +d files(file)(+1)]
             1["compileUnit:" +d comileUnit]
            ]
           1
          "}"
        @format:file(filePlace * string) "("filePlace "," string ")"
       *)
    ({loadedFiles: (filePlace * string) list} * AbsynInterface.compileUnit)
*)

  val debugPrint = fn s => if !Bug.debugPrint then print s else ()
  fun printStopAt stopAt =
      debugPrint (Bug.prettyPrint (format_stopAt stopAt))
(*
  fun printCode code =
      debugPrint (Bug.prettyPrint (format_code code))
*)
(*
  fun printInterfaceName interfaceName =
      debugPrint (Bug.prettyPrint (InterfaceName.format_interface_name interfaceName))
*)
  fun printFileName fileName =
      debugPrint (Bug.prettyPrint (Filename.format_filename fileName))
(*
  fun printInterfaceNameList interfaceNameList =
      app (fn i => (printInterfaceName i; debugPrint "\n")) interfaceNameList
*)
  fun printResult result =
      debugPrint (Bug.prettyPrint (format_result result))
  fun printOptions options =
      debugPrint (Bug.prettyPrint (format_options options))

(*
  fun printCompileUnit unit =
      debugPrint (Bug.prettyPrint (AbsynInterface.format_compileUnit unit))
*)
  end

  (*%  @formatter(Filename.filename) Filename.format_filename *)
  exception

  (*%
   * @format(n)
   * "unsupported" +d "pointer" +d "size:" +d n
   *)
  UnsupportedPointerSize of int

  and
  (*%
   * @format(file)
   * "illegal" +d "builtin" +d "interface:" +d file
   *)
  IllegalBuiltin of Filename.filename

end
